package main

import (
	"fmt"
	"math/rand"
	"runtime"
	"sync"
	"time"
)

func main()  {
	//扇出用于描述启动多个goroutine以处理来自pipeline的输入的过程，
	//扇入是描述将多个结果组合到一个channel的过程中的术语。


	//示例：找到素数菲常低效的函数
	rand := func() interface{} { return rand.Intn(50000000) }
	done := make(chan interface{})
	defer close(done)
	start := time.Now()
	randIntStream := toInt(done,repeatFn(done,rand))
	fmt.Println("Primes:")
	for prime := range take(done,primeFinder(done,randIntStream),10) {
		fmt.Printf("\t%d\n",prime)
	}
	fmt.Printf("Search took: %v",time.Since(start))


	//优化后的函数
	fanIn := func(
		done <-chan interface{},
		channels ...<-chan interface{},
	) <-chan interface{} {    //
		var wg sync.WaitGroup  //
		multiplexedStream := make(chan interface{})

		multiplex := func(c <-chan interface{}) {  //
			defer wg.Done()
			for i := range c {
				select {
				case <-done:
					return
				case multiplexedStream <- i:
				}
			}
		}

		//从所有的channel里取值
		wg.Add(len(channels))  //
		for _,c := range channels {
			go multiplex(c)
		}


		//等待所有的读操作结束
		go func() {    //
			wg.Wait()
			close(multiplexedStream)
		}()
		return multiplexedStream
	}

	done := make(chan interface{})
	defer close(done)

	start := time.Now()

	rand := func() interface{} { return rand.Intn(50000000)}

	randIntStream := toInt(done,repeatFn(done,rand))

	numFinders := runtime.NumCPU()
	fmt.Printf("Spinning up %d prime finders.\n",numFinders)
	finders := make([]<-chan interface{},numFinders)
	fmt.Println("Primes:")
	for i := 0; i < numFinders; i++ {
		finders[i] = primeFinder(done,randIntStream)
	}
	for prime := range take(done,fanIn(done,finders...),10) {
		fmt.Printf("\t%d\n",prime)
	}

	fmt.Printf("Search took: %v",time.Since(start))


}





